package com.itheima.nio.tomcat.entry;

import com.itheima.nio.tomcat.domain.HttpRequest;
import com.itheima.nio.tomcat.domain.HttpResponse;
import com.itheima.nio.tomcat.handler.AcceptHandler;
import com.itheima.nio.tomcat.inter.PraseServletConfig;
import com.itheima.nio.tomcat.parse.PropertiesPraseServletConfig;
import com.itheima.nio.tomcat.process.DynamicResourceProcess;
import com.itheima.nio.tomcat.runnable.LoaderResourceRunnable;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * Http服务端代码实现
 */
public class HttpServer {

    public static void main(String[] args) throws IOException {

        // 开启一个读取配置文件的线程
        new Thread(new LoaderResourceRunnable()).start();

        /**
         * 开发步骤：
         *
         * 1. 打开ServerSocketChannel
         * 2. 进行端口号绑定
         * 3. 设置ServerSocketChannel为非阻塞
         * 4. 开启一个选择器
         * 5. 将ServerSocketChannel通道注册到选择器上
         * 6. 轮询调用选择器来进行选择操作
         * 7. 获取所有的有就绪任务的通道
         * 8. 遍历，然后进行判断，根据任务的类型给出相关的处理方案
         *
         */

        // 1. 打开ServerSocketChannel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        // 2. 进行端口号绑定
        serverSocketChannel.socket().bind(new InetSocketAddress(80));

        // 3. 设置ServerSocketChannel为非阻塞
        serverSocketChannel.configureBlocking(false) ;

        // 4. 开启一个选择器
        Selector selector = Selector.open();

        // 5. 将ServerSocketChannel通道注册到选择器上
        serverSocketChannel.register(selector , SelectionKey.OP_ACCEPT) ;

        // 6. 进行循环选择
        while(true) {

            // 进行选择
            int select = selector.select();

            // 判断select
            if(select != 0) {

                // 获取所有的具有就绪任务通道信息的集合
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();

                // 循环遍历
                while(iterator.hasNext()) {

                    SelectionKey selectionKey = iterator.next();        // 获取一个具有就绪任务的通道
                    if(selectionKey.isAcceptable()) {                   // 接收客户端连接的任务

                        // ServerSocketChannel serverSocketChannel1 = (ServerSocketChannel)selectionKey.channel() ;
                        // SocketChannel socketChannel = serverSocketChannel1.accept();        // 接收客户端的连接
                        // socketChannel.configureBlocking(false) ;                            // 将其设置为非阻塞
                        // socketChannel.register(selector , SelectionKey.OP_READ) ;           // 把SocketChannel注册到选择器上

                        // 使用AcceptHandler中的方法去接收客户端连接
                        AcceptHandler acceptHandler = new AcceptHandler() ;
                        acceptHandler.connSocketChannel(selectionKey) ;

                    }else if(selectionKey.isReadable()) {               // 读取客户端发送过来的数据的任务

                        // 创建HttpRequest对象，然后调用parse方法完成数据的解析操作
                        HttpRequest httpRequest = new HttpRequest(selectionKey) ;
                        httpRequest.parse();

                        // 判断当前HttpRequest对象的requestURI属性是否为null或者"",如果是就将这个通道的信息从Selector选择器上移除掉
                        if("".equals(httpRequest.getRequestURI()) || httpRequest.getRequestURI() == null) {

                            // 就将这个通道的信息从Selector选择器上移除掉
                            selectionKey.cancel();
                            continue;
                        }

                        System.out.println("数据解析完毕了.......................");

                        // 判断当前用户请求的是静态资源还是动态资源，根据不同的请求资源路径给出不同的处理
                        String requestURI = httpRequest.getRequestURI() ;

                        // 给出客户端响应
                        HttpResponse httpResponse = new HttpResponse(selectionKey);
                        httpResponse.setHttpRequest(httpRequest);

                        if(requestURI.startsWith("/servlet")) {     // 请求的是动态资源

                            DynamicResourceProcess dynamicResourceProcess = new DynamicResourceProcess() ;
                            dynamicResourceProcess.process(httpRequest , httpResponse);

                        }else {
                            httpResponse.sendStaticResource();                  // 给客户端进行数据响应
                        }

                    }

                    // 把这个通道从集合中移除掉
                    iterator.remove();

                }

            }

        }

    }

}
